require 'treetop'
require 'SweetTea/nodes'
base_path = File.expand_path(File.dirname(__FILE__))
Treetop.load(File.join(base_path, 'grammar.treetop'))

module SweetTea
  class Parser
    def parse code
      parser = SweetTeaParser.new
      results = parser.parse code
      @options = {
        :indent => 0,
        :current_class => nil,
        :init => {
          :args => nil,
          :content => nil
        }
      }
      to_js(results)
    end
    
    def to_js node, inClass = false
      case node.class.to_s
        when "SweetTea::BodyNode"
          all = []
          node.elements.each {|n| all << to_js(n) }
          return all.join
        when "SweetTea::ClassNode"
          className = node.elements[2].text_value
          @options[:current_class] = className
          @options[:indent] += 1
          lines = ""
          node.elements[3].elements.each do |n|
            val = to_js(n, true)
            if val != ""
              lines << "#{val}"
            end
          end
          @options[:indent] -= 1
          @options[:current_class] = nil
          init = @options[:init][:content]
          init_args = @options[:init][:args]
          @options[:init][:content] = nil
          @options[:init][:args] = nil
          return  "#{ind}var #{className} = (function() {\n" +
                  "#{ind}  function #{className}(#{init_args}) {#{init}}\n" +
                  "#{lines}" +
                  "#{ind}  return #{className};\n" +
                  "#{ind}})();\n"
        when "SweetTea::FunctionNode"
          funcName = node.elements[2].text_value
          args = ""
          node.elements[3].elements.each do |n|
            val = n.text_value
            if val != " "
              if args == ""
                args << "#{val}"
              else
                args << ", #{val}"
              end
            end
          end
          lines = ""
          @options[:indent] += 1
          node.elements[4].elements.each do |n|
            val = to_js(n)
            if val != ""
              lines << val
            end
          end
          @options[:indent] -= 1
          if inClass
            if funcName == "init"
              @options[:init][:content] = "\n#{lines}#{ind}" if lines != ""
              @options[:init][:args] = args
              return ""
            else
              return  "#{ind}#{@options[:current_class]}.prototype.#{funcName} = function(#{args}) {\n" +
                      "#{lines}" +
                      "#{ind}};\n"
            end
          else
            return  "#{ind}var #{funcName} = function(#{args}) {\n" +
                    "#{lines}" +
                    "#{ind}};\n"
          end
        when "SweetTea::VariableNode"
          varName = node.elements[2].text_value
          if node.elements[4].elements.nil?
            varValue = "null"
          else
            varValue = to_js(node.elements[4].elements[2])
          end
          if inClass
            return "#{ind}#{@options[:current_class]}.prototype.#{varName} = #{varValue};\n"
          else
            return "#{ind}var #{varName} = #{varValue};\n"
          end
        when "SweetTea::StringLiteral"
          return "\"#{node.elements[1].text_value}\""
        else
          raise "Syntax Error" if node.nil?
          return ""
      end
    end
    
    def ind
      "  " * @options[:indent]
    end
  end
end